From 1155d7dffd3337942cb7583706b429d567d4db86 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 21 Jan 2021 18:35:22 +1100
Subject: [PATCH] disk/lvm: Do not overread metadata

We could reach the end of valid metadata and not realize, leading to
some buffer overreads. Check if we have reached the end and bail.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
---
 grub-core/disk/lvm.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index bd5ae87..742ecd6 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -313,17 +313,23 @@ grub_lvm_detect (grub_disk_t disk,
 	  while (1)
 	    {
 	      grub_ssize_t s;
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      pv = grub_zalloc (sizeof (*pv));
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto pvs_fail_noname;
+
 	      s = q - p;
 	      pv->name = grub_malloc (s + 1);
 	      grub_memcpy (pv->name, p, s);
@@ -366,6 +372,7 @@ grub_lvm_detect (grub_disk_t disk,
 	      continue;
 	    pvs_fail:
 	      grub_free (pv->name);
+	    pvs_fail_noname:
 	      grub_free (pv);
 	      goto fail4;
 	    }
@@ -387,18 +394,24 @@ grub_lvm_detect (grub_disk_t disk,
 	      struct grub_diskfilter_segment *seg;
 	      int is_pvmove;
 
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      lv = grub_zalloc (sizeof (*lv));
 
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto lvs_fail;
+
 	      s = q - p;
 	      lv->name = grub_strndup (p, s);
 	      if (!lv->name)
@@ -570,9 +583,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  stripe->name = grub_malloc (s + 1);
@@ -629,9 +645,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  lvname = grub_malloc (s + 1);
-- 
2.14.2

